<template>
    <div :style="{width:width}">
        <br>
        <Form v-show="_defineIdsFinished" :hide-required-mark="false" :label-colon="true" :model="formData"  ref="ruiFrom" >
            <div :key="defineIndex" v-for="(defineInfo,defineIndex)  in formDefines">
                <Collapse :value="defineInfo.groupName" v-if="defineInfo.group">
                    <Panel :name="defineInfo.groupName">
                        {{defineInfo.groupName}}
                        <div slot="content">
                            <Row type="flex" justify="start">
                                <Col :key="gridIndex" :span="grid.span" v-for="(grid,gridIndex) in defineInfo.grids">
                                    <span :key="itemIndex" v-for="(item,itemIndex) in grid.items">
                                        <FormItem
                                            :label="item.title"
                                            :rules="formRules[item.key]"
                                            :ref="`_rui_item_`+item.key"
                                            :required="item.require"
                                            :label-width="item.labelWidth?item.labelWidth:labelWidth"
                                            :prop="item.key"
                                            v-if="formKeys.includes(item.key)&&!formHideKeys.includes(item.key)">
                                        <rui-item
                                            :formData="formData"
                                            :formHasSlotKeys="formHasSlotKeys"
                                            :formRules="formRules"
                                            :formSimpleItem="formSimpleItem"
                                            :formSlots="formSlots"
                                            :item="item"/>
                                        </FormItem>
                                    </span>
                                </Col>
                            </Row>
                        </div>
                    </Panel>
                </Collapse>
                <div v-else>
                    <Row type="flex" justify="start">
                        <Col :key="gridIndex" :span="grid.span" v-for="(grid,gridIndex) in defineInfo.grids">
                            <span :key="itemIndex" v-for="(item,itemIndex) in grid.items">
                                <FormItem
                                    :label="item.title"
                                    :label-width="item.labelWidth?item.labelWidth:labelWidth"
                                    :prop="item.key"
                                    :ref="`_rui_item_`+item.key"
                                    :required="item.require"
                                    :rules="formRules[item.key]"
                                    v-if="formKeys.includes(item.key)&&!formHideKeys.includes(item.key)">
                                    <rui-item
                                        :formData="formData"
                                        :formHasSlotKeys="formHasSlotKeys"
                                        :formRules="formRules"
                                        :formSimpleItem="formSimpleItem"
                                        :formSlots="formSlots"
                                        :item="item"/>
                                </FormItem>
                            </span>
                        </Col>
                    </Row>
                </div>
            </div>
        </Form>
    </div>
</template>
<script>
    import ruiMixin from '../../mixin/rui-global-components';
    import ruiEleMixin from '../../mixin/rui-element-mixin'
    import RuiItem from './item'
    import validator from '../../validate/rules'
    import dateUtil from '_c/iview/utils/date';

    export default {
        name: 'rui-form',
        mixins: [ruiMixin,ruiEleMixin],
        components: {
            RuiItem
        },
        provide() {
            return {
                RuiForm: this
            };
        },
        props: {
            labelWidth: {
                type: Number,
                require: false,
                default: 150
            },
            readOnly: {
                type: Boolean,
                require: false,
                default: false
            },
            formOptions: {
                type: Array,
                require: true
            },
            width:{
                type:String,
                default:'100%'
            },
            beforeChange:Function,
            afterChange:Function
        },
        data() {
            return {
                defaultFormData: {},
                formData: {},
                backUpData:{},
                formDefines: [],
                formItems: [],
                formSimpleItem: [],
                formRules: {},
                formSlots: {},
                formHasSlotKeys: [],
                formRequiredKeys: [],
                formKeys: [],
                formHideKeys: [],
                formItemsType: {}
            }
        },
        methods: {
            init() {
                if (!this.formOptions || this.formOptions.length == 0) {
                    throw Error('ruiForm组件formOptions定义不合法');
                }
                let self = this;
                this.formOptions.forEach(formDefine => {
                    let defineInfo = {};
                    defineInfo.grids = [];
                    defineInfo.group = formDefine.isGroup ? formDefine.isGroup : false
                    defineInfo.groupName = formDefine.groupName;
                    if (formDefine.hideKey && Array.isArray(formDefine.hideKey)) {
                        formDefine.hideKey.forEach(key => {
                            if (!self.formHideKeys.includes(key)) {
                                self.formHideKeys.push(key);
                            }
                        })
                    }
                    if (formDefine.grids && formDefine.grids.length > 0) {
                        formDefine.grids.forEach(gridInfo => {
                            if (gridInfo.defineId) {
                                if (gridInfo.slots && gridInfo.slots.length > 0) {
                                    gridInfo.slots.forEach(slot => {
                                        self.formSlots[slot.key] = slot.slotName;
                                        self.formHasSlotKeys.push(slot.key);
                                    })
                                }

                                if (gridInfo.readOnlyKeys && gridInfo.readOnlyKeys.length > 0) {
                                    self.formSimpleItem.push(...gridInfo.readOnlyKeys);
                                }

                                let grid = {};
                                grid.span = gridInfo.span ? gridInfo.span : 12
                                grid.items = [];
                                if (gridInfo.fields && gridInfo.fields.length > 0) {
                                    gridInfo.fields.forEach(key=>{
                                       const temp = self.RuiPage.pageData[gridInfo.defineId].fields.filter(value => {
                                            return key ===value.key
                                        })[0];
                                        grid.items.push(self.clone(temp))
                                    })
                                } else {
                                    grid.items.push(...self.clone(self.RuiPage.pageData[gridInfo.defineId].fields))
                                }

                                self.formItems.push(...grid.items);
                                grid.items.forEach(item => {

                                    // 表格所有key
                                    if (!self.formKeys.includes(item.key)) {
                                        self.formKeys.push(item.key);
                                    } else {
                                        throw Error(item.key + '重复')
                                    }
                                    //设置默认精度
                                    if (Number.isNaN(item.scale)) {
                                        item.scale = 2;
                                    }
                                    //设置默认类型 为text
                                    if (!item.type || item.type == '') {
                                        item.type = 'text';
                                    }
                                    item._type = item.type;
                                    //设置默认placeholder
                                    if (!item.placeholder || item.placeholder == '') {
                                        item.placeholder = '请输入' + item.title;
                                    }
                                    //校验规则处理
                                    //初始化规则数组
                                    let itemRules = [];
                                    if (item.type === 'text' || item.type == 'password' || item.type == 'textarea') {
                                        itemRules.push({
                                            required: item.require,
                                            validator: validator.stringValidator,
                                            message: item.title + '值不能为空'
                                        })
                                        itemRules.push({
                                            max: item.maxlength?item.maxlength:100,
                                            message: "最多输入"+(item.maxlength?item.maxlength:100)+"个字符",
                                            trigger: "blur"
                                        })
                                    } else if (item.type == 'url') {
                                        itemRules.push({
                                            required: item.require,
                                            validator: validator.stringValidator,
                                            message: item.title + '值不能为空'
                                        })
                                        itemRules.push({type: 'url', message: '网址格式不正确'})
                                        itemRules.push({
                                            max: item.maxlength?item.maxlength:100,
                                            message: "最多输入"+(item.maxlength?item.maxlength:100)+"个字符",
                                            trigger: "blur"
                                        })
                                    } else if (item.type == 'email') {
                                        itemRules.push({
                                            required: item.require,
                                            validator: validator.stringValidator,
                                            message: item.title + '值不能为空'
                                        })
                                        itemRules.push({type: 'email', message: '邮箱格式不正确'})
                                        itemRules.push({
                                            max: item.maxlength?item.maxlength:100,
                                            message: "最多输入"+(item.maxlength?item.maxlength:100)+"个字符",
                                            trigger: "blur"
                                        })
                                    } else if (item.type == 'mobile') {
                                        itemRules.push({
                                            required: item.require,
                                            validator: validator.stringValidator,
                                            message: item.title + '值不能为空'
                                        })
                                        itemRules.push({message: '手机号格式不正确', validator: validator.mobileValidator})
                                    } else if (item.type == 'radio') {
                                        itemRules.push({
                                            required: item.require,
                                            validator: validator.stringValidator,
                                            trigger: 'change',
                                            message: '请选择一项'
                                        })
                                    } else if (item.type == 'checkbox') {
                                        itemRules.push({
                                            required: item.require,
                                            validator: validator.arrayValidator,
                                            trigger: 'change',
                                            message: '请选择一项'
                                        })
                                    } else if (item.type == 'date') {
                                        itemRules.push({
                                            required: item.require,
                                            validator: validator.dateValidator,
                                            message: item.title + '值不能为空'
                                        })
                                    } else if (item.type == 'dateRange') {
                                        itemRules.push({
                                            required: item.require,
                                            validator: validator.dateRangeValidator,
                                            message: item.title + '值不能为空'
                                        })
                                    } else if (item.type == 'datetime') {
                                        itemRules.push({
                                            required: item.require,
                                            validator: validator.dateValidator,
                                            trigger: 'change',
                                            message: item.title + '值不能为空'
                                        })
                                    } else if (item.type == 'datetimeRange') {
                                        itemRules.push({
                                            required: item.require,
                                            validator: validator.dateRangeValidator,
                                            message: item.title + '值不能为空'
                                        })
                                    } else if (item.type == 'time') {
                                        itemRules.push({
                                            required: item.require,
                                            validator: validator.dateValidator,
                                            trigger: 'change',
                                            message: item.title + '值不能为空'
                                        })
                                    } else if (item.type == 'timeRange') {
                                        itemRules.push({
                                            required: item.require,
                                            validator: validator.dateRangeValidator,
                                            trigger: 'change',
                                            message: item.title + '值不能为空'
                                        })
                                    } else if (item.type == 'singleSelect') {
                                        itemRules.push({
                                            required: item.require,
                                            validator: validator.stringValidator,
                                            message: '请至少选择一项'
                                        })
                                    } else if (item.type == 'multipleSelect') {
                                        itemRules.push({
                                            required: item.require,
                                            validator: validator.arrayValidator,
                                            message: '请至少选择一项'
                                        })
                                    } else if (item.type == 'number') {
                                        itemRules.push({
                                            required: item.require,
                                            validator: validator.stringValidator,
                                            message: item.title + '值不能为空'
                                        })
                                    } else if (item.type == 'currency') {
                                        itemRules.push({
                                            required: item.require,
                                            validator: validator.stringValidator,
                                            message: item.title + '值不能为空'
                                        })
                                    }
                                    //设置格式样式
                                    if (!item.format) {
                                        if (item.type == 'date' || item.type == 'dateRange') {
                                            item.format = 'yyyy-MM-dd';
                                        } else if (item.type == 'datetime' || item.type == 'datetimeRange') {
                                            item.format = 'yyyy-MM-dd HH:mm:ss';
                                        } else if (item.type == 'time' || item.type == 'timeRange') {
                                            item.format = 'HH:mm:ss';
                                        }
                                    }
                                    //设定参数
                                    self.formItemsType[item.key] = {type: item.type, format: item.format};
                                    // self.formRules[item.key].push(rule);
                                    self.formRules[item.key] = itemRules;
                                    //添加自定规则
                                    if (item.rules && Array.isArray(item.rules)) {
                                        self.formRules[item.key].push(...item.rules)
                                    }

                                    //默认值处理
                                    if (item.type == 'dateRange' || item.type == 'datetimeRange' || item.type == 'timeRange') {
                                        self.$set(self.formData, item.key, []);
                                        self.$set(self.defaultFormData, item.key, []);
                                        self.$set(self.backUpData, item.key, []);
                                    } else if (item.type == 'checkbox' || item.type == 'multipleSelect') {
                                        self.$set(self.formData, item.key, []);
                                        self.$set(self.defaultFormData, item.key, []);
                                        self.$set(self.backUpData, item.key, []);
                                    } else if (item.type == 'currency') {
                                        item.dataFormater = this.currencyFormat
                                        self.$set(self.formData, item.key, null);
                                        self.$set(self.defaultFormData, item.key, null);
                                        self.$set(self.backUpData, item.key, null);
                                    } else if (item.type == 'number') {
                                        item.dataFormater = this.numberFormat
                                        self.$set(self.formData, item.key, null);
                                        self.$set(self.defaultFormData, item.key, null);
                                        self.$set(self.backUpData, item.key, null);
                                    } else if (item.type == 'date') {
                                        self.$set(self.formData, item.key, null);
                                        self.$set(self.defaultFormData, item.key, null);
                                        self.$set(self.backUpData, item.key, null);
                                    } else {
                                        if (item.default) {
                                            self.$set(self.formData, item.key, item.default);
                                            self.$set(self.defaultFormData, item.key, item.default);
                                            self.$set(self.backUpData, item.key, item.default);
                                        } else {
                                            self.$set(self.formData, item.key, '');
                                            self.$set(self.defaultFormData, item.key, '');
                                            self.$set(self.backUpData, item.key, '');
                                        }
                                    }
                                    //动态设置watch
                                    if(self.beforeChange||self.afterChange){
                                        self.$watch('formData.'+item.key,
                                            function(afterValue,beforeValue){
                                                if(self.beforeChange) {
                                                    const checkResult = self.beforeChange(item.key
                                                        , self.formatData(item.key, beforeValue, item.format)
                                                        , self.formatData(item.key, afterValue, item.format));
                                                    if (!checkResult && afterValue !== self.backUpData[item.key]) {
                                                        self.$nextTick(() => {
                                                            self.setFiledValue(item.key, self.backUpData[item.key])
                                                        });
                                                    } else {
                                                        if (self.afterChange) {
                                                            self.afterChange(item.key, self.formatData(item.key, afterValue, item.format));
                                                        }
                                                    }
                                                }else{
                                                    if (self.afterChange) {
                                                        self.afterChange(item.key, self.formatData(item.key, afterValue, item.format));
                                                    }
                                                }
                                            },
                                            {deep: true}
                                            )
                                    }
                                    self.prepareDicInfo(item);
                                    if (item.readOnly && !self.formSimpleItem.includes(item.key)) {
                                        self.formSimpleItem.push(item.key);
                                    }
                                    if (self.readOnly && !self.formSimpleItem.includes(item.key)) {
                                        self.formSimpleItem.push(item.key);
                                    }

                                });
                                defineInfo.grids.push(grid);
                            }
                        });
                    }
                    self.formDefines.push(defineInfo);
                })
                //校验类型是否输入组件定义类型
                self.formItems.forEach(item => {
                    if (!self.allTypes.includes(item.type)) {
                        throw Error(item.key + '[type]定义不合法,请在' + self.allTypes + '中选择');
                    }
                });
                this.$emit('ruiFormFinished');
            },
            formatData(type,value,format){
                if (type == 'date' || type == 'datetime' || type == 'time') {
                    if (value && value instanceof Date) {
                        return  dateUtil.format(value, format)
                    }
                } else if (type == 'dateRange' || type == 'datetimeRange' || type == 'timeRange') {
                    if (value && (Array.isArray(value))) {
                        let temp = [];
                        value.forEach(dateItem => {
                            if (dateItem && dateItem instanceof Date) {
                                temp.push(dateUtil.format(dateItem, format))
                            } else {
                                temp.push(dateItem)
                            }
                        })
                        return  temp;
                    }
                }
                return value;
            },
            updateFormData(data) {
                this.formData = data;
            },
            callValidate(key){
                let self = this;
                if(!self.formHideKeys.includes(key)){
                    self.$nextTick(()=>{
                        const field = self.$refs['ruiFrom'].fields.filter(field => field.prop === key)[0];
                        if(field) {
                            self.$refs['ruiFrom'].validateField(key, errors => {

                            });
                        }
                    })
                }
            },
            setAllFieldRequired(required) {
                let self = this;
                // this.formKeys.forEach(key => {
                    self.formItems.forEach(item => {
                        item.require = required;
                        (self.formRules[item.key])[0].required = required
                        self.callValidate(item.key);
                    });
                    // self.callValidate(key);
                // })
            },
            setAllFieldReadOnly(readOnly) {
                let self = this;
                this.formKeys.forEach(key => {
                    self.setFieldReadOnly(key, readOnly);
                })
            },
            setFiledHide(key, hide) {
                let self = this;
                if (!hide) {
                    if (self.formHideKeys.includes(key)) {
                        let index = self.formHideKeys.indexOf(key);
                        if (index > -1) {
                            self.formHideKeys.splice(index, 1);
                        }
                    }
                } else {
                    if (!self.formHideKeys.includes(key)) {
                        self.formHideKeys.push(key);
                    }
                }
            },
            setFieldRequired(key, required) {
                let self = this;
                if (this.formKeys.includes(key)) {
                    self.formItems.forEach(item => {
                        if (item.key == key) {
                            item.require = required;
                            self.callValidate(key);
                        }
                    });
                    (self.formRules[key])[0].required = required
                }
            },
            setFieldReadOnly(key, readOnly) {
                if (this.formKeys.includes(key)) {
                    if (!this.formSimpleItem.includes(key) && readOnly) {
                        this.formSimpleItem.push(key);
                    } else if (this.formSimpleItem.includes(key) && !readOnly) {
                        let index = this.formSimpleItem.indexOf(key);
                        this.formSimpleItem.splice(index, 1);
                    }
                }
            },
            resetFrom() {
                this.backUpData = this.clone(this.defaultFormData)
                this.formData = this.clone(this.defaultFormData)
                this.$refs['ruiFrom'].resetFields();
            },
            setFiledValue(key, value) {
                this.formData[key] = value;
            },
            getForm() {
                return this.$refs['ruiFrom'];
            },
            getFormData() {
                let rtn = this.clone(this.formData);
                let self = this;
                Object.keys(this.formData).forEach(key => {
                    if(self.formKeys.includes(key)) {
                        let {type, format} = self.formItemsType[key];
                        if (type == 'date' || type == 'datetime' || type == 'time') {
                            if (rtn[key] && rtn[key] instanceof Date) {
                                rtn[key] = dateUtil.format(rtn[key], format)
                            }
                        } else if (type == 'dateRange' || type == 'datetimeRange' || type == 'timeRange') {
                            if (rtn[key] && (Array.isArray(rtn[key]))) {
                                let temp = [];
                                rtn[key].forEach(dateItem => {
                                    if (dateItem && dateItem instanceof Date) {
                                        temp.push(dateUtil.format(dateItem, format))
                                    } else {
                                        temp.push(dateItem)
                                    }
                                })
                                rtn[key] = temp;
                            }
                        }
                    }
                })
                return rtn;
            },
            calDependIds(){
                let ids=[];
                this.formOptions.forEach(row=>{
                    row.grids.forEach(grid=>{
                        if(!ids.includes(grid.defineId)){
                            ids.push(grid.defineId)
                        }
                    })
                })

                return ids;
            }
        },
        computed: {
        },
        watch: {

        },
        mounted() {
        },
        beforeMount() {
        }
    }
</script>
